/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = db2_exter.c                                                   */
/*  NOTE      = TDS 请求解析                                                  */
/*  DATE      = 2015/03/19 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "db2_froca.h"
#include "db2_base_type.h"

/*******************************************************************************
*  FUNC     :  跳过NVCM 和 NVCS
*  ARGS     :  p_st_data (实际数据)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_exter_nvcm_nvcs(Frbyte_Packet *p_st_data)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_flg = 0;
    uint16_t u16_len = 0;

    /* 取得NVCM NULLABLE FLAG */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_char(p_st_data, &u8_flg);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* NVCM是NULL */
    if (u8_flg == 0xFF)
    {
        /* 取得NVCS NULLABLE FLAG */
        i_ret = bytebuff_get_char(p_st_data, &u8_flg);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* NVCS不是NULL */
        if (u8_flg == 0x00)
        {
            if (bytebuff_remaining(p_st_data) < 2)
            {
                return APM_L7_ANALYZE_TODO;
            }
            i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (bytebuff_remaining(p_st_data) < u16_len)
            {
                return APM_L7_ANALYZE_TODO;
            }
            bytebuff_skip(p_st_data, u16_len);
        }
        else if (u8_flg != 0xFF)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else if (u8_flg == 0x00)
    {
        if (bytebuff_remaining(p_st_data) < 2)
        {
            return APM_L7_ANALYZE_TODO;
        }
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        if (bytebuff_remaining(p_st_data) < u16_len + 1)
        {
            return APM_L7_ANALYZE_TODO;
        }
        bytebuff_skip(p_st_data, u16_len);
        /* 取得NVCS NULLABLE FLAG */
        i_ret = bytebuff_get_char(p_st_data, &u8_flg);
        if (i_ret != FR_SUCC || u8_flg != 0xFF)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else
    {
        return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLDCXGRP
*  ARGS     :  p_st_data (实际数据)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_exter_sqldcxgrp(Frbyte_Packet *p_st_data)

{
    /* SQLDCXGRP格式
    *  SQLDCXGRP = SQLDCXRDB(VCS)
    *              SQLDCXSCH_m(NVCM)
    *              SQLDCXSCH_s(NVCS)
    *              SQLDCXNAM_m(NVCM)
    *              SQLDCXNAM_s(NVCS)
    *              SQLDCXTBLN_m(NVCM)
    *              SQLDCXTBLN_s(NVCS)
    *              SQLDCXCRDB(VCS)
    *              SQLDCXCSCH_m(NVCM)
    *              SQLDCXCSCH_s(NVCS)
    *              SQLDCXCNAM_m(NVCM)
    *              SQLDCXCNAM_s(NVCS)
    *              SQLDCXRRDB(VCS)
    *              SQLDCXRSCH_m(NVCM)
    *              SQLDCXRSCH_s(NVCS)
    *              SQLDCXRNAM_m(NVCM)
    *              SQLDCXRNAM_s(NVCS)
    *              SQLDCXTRDB(VCS)
    *              SQLDCXTSCH_m(NVCM)
    *              SQLDCXTSCH_s(NVCS)
    *              SQLDCXTNAM_m(NVCM)
    *              SQLDCXTNAM_s(NVCS)
    *              SQLDCXMOD_m(NVCM)
    *              SQLDCXMOD_s(NVCS)
    *              SQLDCXRMOD_m(NVCM)
    *              SQLDCXRMOD_s(NVCS)
    */
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_flg = 0;
    uint16_t u16_len = 0;

    /* SQLDCXGRP FLAG */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        return APM_L7_ANALYZE_TODO;
    }
    /* SQLDCXGRP FLAG */
    i_ret = bytebuff_get_char(p_st_data, &u8_flg);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* SQLDCXGRP结束 */
    if (u8_flg == 0xFF)
    {
        return APM_L7_ANALYZE_SUCC;
    }
    else if (u8_flg != 0x00)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* SQLDCXRDB(VCS) */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_len)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, u16_len);

    /* SQLDCXSCH_m(NVCM ) + SQLDCXSCH_s(NVCS ) */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    /* SQLDCXNAM_m(NVCM) + SQLDCXNAM_s(NVCS) */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    /* SQLDCXTBLN_m(NVCM) + SQLDCXTBLN_s(NVCS) */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* SQLDCXCRDB(VCS) */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_len)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, u16_len);

    /* SQLDCXCSCH_m(NVCM) + SQLDCXCSCH_s(NVCS) */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    /* SQLDCXCNAM_m(NVCM) + SQLDCXCNAM_s(NVCS) */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* SQLDCXRRDB(VCS) */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_len)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, u16_len);

    /* SQLDCXRSCH_m(NVCM) + SQLDCXRSCH_s(NVCS) */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    /* SQLDCXRNAM_m(NVCM) + SQLDCXRNAM_s(NVCS) */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* SQLDCXTRDB(VCS) */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_len)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, u16_len);

    /* SQLDCXTSCH_m(NVCM) + SQLDCXTSCH_s(NVCS) */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    /* SQLDCXTNAM_m(NVCM) + SQLDCXTNAM_s(NVCS) */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    /* SQLDCXMOD_m(NVCM) + SQLDCXMOD_s(NVCS) */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    /* SQLDCXRMOD_m(NVCM) + SQLDCXRMOD_s(NVCS) */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLCNROW
*  ARGS     :  p_st_data (实际数据)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_exter_sqlcnrow(Frbyte_Packet *p_st_data)
{
    /* SQLCNROW格式
    *  SQLCNROW = SQLCNSTATE(I4)
    *             SQLCNSTATUS(I4)
    *             SQLCNATYPE(1-byte FCS)
    *             SQLCNETYPE(1-byteFCS)
    *             SQLCNPRDID(8-byteFCS)
    *             SQLCNRDB(VCS)
    *             SQLCNCLASS(VCS)
    *             SQLCNAUTHID(VCS)
    */
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint16_t u16_len = 0;

    /* 18是SQLCNSTATE + SQLCNSTATUS + SQLCNATYPE + SQLCNETYPE + SQLCNPRDID */
    if (bytebuff_remaining(p_st_data) < 18 + 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, 18);

    /* 跳过SQLCNRDB */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_len + 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, u16_len);

    /* 跳过SQLCNCLASS */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_len + 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, u16_len);

    /* 跳过SQLCNAUTHID */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_len)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, u16_len);

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLDCROW
*  ARGS     :  p_st_data (实际数据)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  遗留长度必须大于实际数据长度
*******************************************************************************/
int db2_parse_exter_sqldcrow(Frbyte_Packet *p_st_data)
{
    /* SQLDCROW格式
    *  SQLDCROW = SQLDCCODE(4-byte integer)
    *             SQLDCSTATE(5-byte character field)
    *             SQLDCREASON(4-byte integer)
    *             SQLDCLINEN(4-byte integer)
    *             SQLDCROWN(8-byte integer)
    *             SQLDCER01(4-byte integer)
    *             SQLDCER02(4-byte integer)
    *             SQLDCER03(4-byte integer)
    *             SQLDCER04(4-byte integer)
    *             SQLDCPART(4-byte integer)
    *             SQLDCPPOP(4-byte integer)
    *             SQLDCMSGID(10-byte character field)
    *             SQLDCMDE(8-byte character field)
    *             SQLDCPMOD(5-byte character field)
    *             SQLDCRDB(variable character field)
    *             SQLDCTOKS(参照SQLDCTOKS)
    *             SQLDCMSG_m(nullable variable character field)
    *             SQLDCMSG_s(nullable variable character field)
    *             SQLDCCOLN_m(nullable variable character field)
    *             SQLDCCOLN_s(nullable variable character field)
    *             SQLDCCURN_m(nullable variable character field)
    *             SQLDCCURN_s(nullable variable character field)
    *             SQLDCPNAM_m(nullable variable character field)
    *             SQLDCPNAM_s(nullable variable character field)
    *             SQLDCXGRP(参照SQLDCXGRP)
    */
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_flg = 0;
    uint16_t u16_num = 0;
    uint16_t u16_len = 0;

    /* 74是SQLDCCODE到SQLDCPMOD的长度 + SQLDCRDB的长度位 */
    if (bytebuff_remaining(p_st_data) < 74)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, 72);

    /* 跳过SQLDCRDB */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_len + 1)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, u16_len);

    /* 跳过SQLDCTOKS */
    i_ret = bytebuff_get_char(p_st_data, &u8_flg);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (u8_flg == 0x00)
    {
        /* 取得SQLNUMROW */
        if (bytebuff_remaining(p_st_data) < 2)
        {
            return APM_L7_ANALYZE_TODO;
        }
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_num, BYTE_LITTLE_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 解析SQLTOKROW */
        while (u16_num)
        {
            u16_num--;
            i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                return i_ret;
            }
        }
    }
    else if (u8_flg != 0xFF)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* SQLDCMSG_m + SQLDCMSG_s */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    /* SQLDCCOLN_m + SQLDCCOLN_s */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    /* SQLDCCURN_m + SQLDCCURN_s */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }
    /* SQLDCPNAM_m + SQLDCPNAM_s */
    i_ret = db2_parse_exter_nvcm_nvcs(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* 解析SQLDCXGRP */
    i_ret = db2_parse_exter_sqldcxgrp(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLDIAGCN
*  ARGS     :  p_st_data (实际数据)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_exter_sqldiagcn(Frbyte_Packet *p_st_data)
{
    /* SQLDIAGCN格式
    *  SQLDIAGCN = SQLNUMROW
    *              SQLCNROW(参照SQLCNROW)
    */
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_flg = 0;
    uint16_t u16_num = 0;

    /* 根据协议SQLDIAGCN必须大于等于1 */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        return APM_L7_ANALYZE_TODO;
    }
    /* SQLDIAGCN FLAG */
    i_ret = bytebuff_get_char(p_st_data, &u8_flg);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* SQLDIAGCN结束 */
    if (u8_flg == 0xFF)
    {
        return APM_L7_ANALYZE_SUCC;
    }
    else if (u8_flg != 0x00)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得SQLNUMROW */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_num, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 解析SQLCNROW */
    while (u16_num)
    {
        u16_num--;
        i_ret = db2_parse_exter_sqlcnrow(p_st_data);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLDIAGCI
*  ARGS     :  p_st_data (实际数据)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_exter_sqldiagci(Frbyte_Packet *p_st_data)
{
    /* SQLDIAGCI格式
    *  SQLDIAGCI = SQLNUMROW
    *              SQLDCROW(参照SQLDCROW)
    */
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_flg = 0;
    uint16_t u16_num = 0;

    /* SQLDIAGCI FLAG */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_char(p_st_data, &u8_flg);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* SQLDIAGCI结束 */
    if (u8_flg == 0xFF)
    {
        return APM_L7_ANALYZE_SUCC;
    }
    else if (u8_flg != 0x00)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得SQLNUMROW */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_num, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 解析sqldcrow */
    while (u16_num)
    {
        u16_num--;
        i_ret = db2_parse_exter_sqldcrow(p_st_data);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLDIAGSTT
*  ARGS     :  p_st_data (实际数据)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_exter_sqldiagstt(Frbyte_Packet *p_st_data)
{
    /* SQLDIAGSTT格式
    *  SQLDIAGSTT = SQLDSFCOD(4-byte integer)
    *               SQLDSCOST(4-byte integer)
    *               SQLDSLROW(4-byte integer)
    *               SQLDSNPM(4-byte integer)
    *               SQLDSNRS(4-byte integer)
    *               SQLDSRNS(4-byte integer)
    *               SQLDSDCOD(4-byte integer)
    *               SQLDSROWC(8-byte integer)
    *               SQLDSNROW(8-byte integer)
    *               SQLDSROWCS(8-byte integer)
    *               SQLDSACON(1-byte character fields)
    *               SQLDSACRH(1-byte character fields)
    *               SQLDSACRS(1-byte character fields)
    *               SQLDSACSL(1-byte character fields)
    *               SQLDSACSE(1-byte character fields)
    *               SQLDSACTY(1-byte character fields)
    *               SQLDSCERR(1-byte character fields)
    *               SQLDSMORE(1-byte character fields)
    */
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_flg = 0;

    /* 根据协议SQLDIAGSTT必须大于等于1 */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        return APM_L7_ANALYZE_TODO;
    }
    /* SQLDIAGSTT FLAG */
    i_ret = bytebuff_get_char(p_st_data, &u8_flg);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* SQLDIAGSTT结束 */
    if (u8_flg == 0xFF)
    {
        return APM_L7_ANALYZE_SUCC;
    }
    else if (u8_flg != 0x00)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /*
    *  根据协议可知：有(7 * (4-byte integer) + 3 * (8-byte integer)
    *  + 8 * (1-byte character fields))
    */
    if (bytebuff_remaining(p_st_data) < 7 * 4 + 3 * 8 + 8 * 1)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, 7 * 4 + 3 * 8 + 8 * 1);

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLDIAGGRP
*  ARGS     :  p_st_data (实际数据)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_exter_sqldiaggrp(Frbyte_Packet *p_st_data)
{
    /* SQLDIAGGRP格式
    *  SQLDIAGGRP = SQLDIAGSTT(参照SQLDIAGSTT)
    *               SQLDIAGCI(参照SQLDIAGCI)
    *               SQLDIAGCN(参照SQLDIAGCN)
    */
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_flg = 0;

    /* SQLDIAGGRP FLAG */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_char(p_st_data, &u8_flg);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* SQLDIAGGRP结束 */
    if (u8_flg == 0xFF)
    {
        return APM_L7_ANALYZE_SUCC;
    }
    else if (u8_flg != 0x00)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* SQLDIAGSTT */
    i_ret = db2_parse_exter_sqldiagstt(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* SQLDIAGCI */
    i_ret = db2_parse_exter_sqldiagci(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* SQLDIAGCN */
    i_ret = db2_parse_exter_sqldiagcn(p_st_data);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLCAXGRP
*  ARGS     :  p_st_private (DB2私有数据)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_exter_sqlcaxgrp(L7session_db2_private *p_st_private)
{
    /* SQLCAXGRP格式
    *  SQLCAXGRP = SQLERRD1(4-byte integer)
    *              SQLERRD2(4-byte integer)
    *              SQLERRD3(4-byte integer: effect rows)
    *              SQLERRD4(4-byte integer)
    *              SQLERRD5(4-byte integer)
    *              SQLERRD6(4-byte integer)
    *              SQLWARN0(1-byte character fields)
    *              SQLWARN1(1-byte character fields)
    *              SQLWARN2(1-byte character fields)
    *              SQLWARN3(1-byte character fields)
    *              SQLWARN4(1-byte character fields)
    *              SQLWARN5(1-byte character fields)
    *              SQLWARN6(1-byte character fields)
    *              SQLWARN7(1-byte character fields)
    *              SQLWARN8(1-byte character fields)
    *              SQLWARN9(1-byte character fields)
    *              SQLWARNA(1-byte character fields)
    *              SQLRDBNAME(A variable character string)
    *              SQLERRMSG_m(A variable character string)
    *              SQLERRMSG_s(A variable character string)
    */
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_flg = 0;
    uint16_t u16_len = 0;
    Frbyte_Packet *p_st_data = p_st_private->p_st_fragment->p_st_data;

    /* SQLCAGRP FLAG */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        return APM_L7_ANALYZE_TODO;
    }
    /* SQLCAXGRP FLAG */
    i_ret = bytebuff_get_char(p_st_data, &u8_flg);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* SQLCAXGRP结束 */
    if (u8_flg == 0xFF)
    {
        return APM_L7_ANALYZE_SUCC;
    }
    else if (u8_flg != 0x00)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 至少有41(6*(4-byte integer) + 11*(1-byte character)
       + SQLRDBNAME + SQLERRMSG_m + SQLERRMSG_s) */
    if (bytebuff_remaining(p_st_data) < 41)
    {
        return APM_L7_ANALYZE_TODO;
    }

    /* 跳过SQLERRD1,SQLERRD2,SQLERRD3,SQLERRD4,SQLERRD5,SQLERRD5,SQLWARN0~SQLWARNA */
    bytebuff_skip(p_st_data, 4 * 6 + 11 * 1);

    /* SQLRDBNAME */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_len + 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, u16_len);

    /* SQLERRMSG_m */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_len + 2)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, u16_len);

    /* SQLERRMSG_s */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    if (bytebuff_remaining(p_st_data) < u16_len)
    {
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, u16_len);

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SQLCAGRP
*  ARGS     :  p_st_private (DB2私有数据)
*           :  p_i_sqlcode(SQLCODE)
*           :  p_sqlstate(SQLSTATE)
*           :  p_i_effect_rows(effect_rows)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_sqlstate必须是长度大于等于6
*******************************************************************************/
int db2_parse_exter_sqlcagrp(L7session_db2_private *p_st_private
                            , int *p_i_sqlcode
                            , char *p_sqlstate)
{
    /* SQLCAGRP格式
    *  SQLCAGRP = SQLCODE(4-byte integer)
    *             SQLSTATE(5-byte character field)
    *             SQLERRPROC(8-byte character field)
    *             SQLCAXGRP(参照SQLCAXGRP)
    *             SQLDIAGGRP(参照SQLDIAGGRP)
    */

    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_flg = 0;
    uint32_t u32_sqlcode = 0;
    uint32_t u32_sqlcode1 = 0;
    uint32_t u32_sqlcode2 = 0;
    int i_sqlcode = 0;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* SQLCAGRP FLAG */
    if (bytebuff_remaining(p_st_data) < 1)
    {
        return APM_L7_ANALYZE_TODO;
    }
    i_ret = bytebuff_get_char(p_st_data, &u8_flg);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* SQLCAGRP结束 */
    if (u8_flg == 0xFF)
    {
        return APM_L7_ANALYZE_SUCC;
    }
    else if (u8_flg != 0x00)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 至少有19(SQLCODE:4 + SQLSTATE:5 + SQLERRPROC:8 + SQLCAXGRP:1 + SQLCAXGRP:1) */
    if (bytebuff_remaining(p_st_data) < 19)
    {
        return APM_L7_ANALYZE_TODO;
    }

    /* 取得SQLCODE */
    switch(p_st_sess->i_ser_typdef)
    {
        /* X86/VAX是字节序是little */
        case DRDA_TYPDEF_QTDSQLX86:
        case DRDA_TYPDEF_QTDSQLVAX:
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_sqlcode, BYTE_LITTLE_ENDIAN);
            break;

        /* 370/400/ASC是字节序是big */
        case DRDA_TYPDEF_QTDSQL370:
        case DRDA_TYPDEF_QTDSQL400:
        case DRDA_TYPDEF_QTDSQLASC:
            i_ret = bytebuff_get_int(p_st_data, 4, &u32_sqlcode, BYTE_BIG_ENDIAN);
            break;

        default:
            i_ret = FR_FAIL;
    }
    /* 结果判定 */
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    *p_i_sqlcode = (int)u32_sqlcode;

    /* 取得SQLSTATE */
    i_ret = bytebuff_get_bytes(p_st_data, p_sqlstate, 5);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 如果链接session信息是不定的，可以根据错误信息进行修正 */
    if (p_st_sess->i_confirmed_flg == DB2_FALSE)
    {
        if (memcmp(p_sqlstate, "00", 2) == 0  /* SQLSTATE为00开头表示完全成功 */
            || memcmp(p_sqlstate, "01", 2) == 0 /* SQLSTATE为01开头表示警告 */
            || memcmp(p_sqlstate, "02", 2) == 0) /* SQLSTATE为02开头表示无数据 */
        {
            /* 在上述情况下表示无错误，error code正常时大于0 */
            if (*p_i_sqlcode < 0 || *p_i_sqlcode > 99999)
            {
                /* 修正链接session信息 */
                switch (p_st_sess->i_ser_typdef)
                {
                    /* 小头的转大头 */
                    case DRDA_TYPDEF_QTDSQLX86:
                    case DRDA_TYPDEF_QTDSQLVAX:
                        u32_sqlcode1 = htonl(u32_sqlcode);
                        *p_i_sqlcode = (int)u32_sqlcode1;
                        p_st_sess->i_ser_typdef = DRDA_TYPDEF_QTDSQLASC;
                        break;

                    /* 大头的转小头 */
                    case DRDA_TYPDEF_QTDSQL370:
                    case DRDA_TYPDEF_QTDSQL400:
                    case DRDA_TYPDEF_QTDSQLASC:
                        u32_sqlcode1 = ntohl(u32_sqlcode);
                        *p_i_sqlcode = (int)u32_sqlcode1;
                        p_st_sess->i_ser_typdef = DRDA_TYPDEF_QTDSQLX86;
                        break;
                }
            }
        }
        else if (strchr("02345", *p_sqlstate)
                 && strchr("0123456789ABDEFKNU", *p_sqlstate + 1))
        {
            /* 在上述情况下表示有错误，error code正常时小于0 */
            if (*p_i_sqlcode > 0 || *p_i_sqlcode < -99999)
            {
                /* 修正链接session信息 */
                switch (p_st_sess->i_ser_typdef)
                {
                    /* 小头的转大头 */
                    case DRDA_TYPDEF_QTDSQLX86:
                    case DRDA_TYPDEF_QTDSQLVAX:
                        u32_sqlcode1 = htonl(u32_sqlcode);
                        *p_i_sqlcode = (int)u32_sqlcode1;
                        p_st_sess->i_ser_typdef = DRDA_TYPDEF_QTDSQLASC;
                        break;

                    /* 大头的转小头 */
                    case DRDA_TYPDEF_QTDSQL370:
                    case DRDA_TYPDEF_QTDSQL400:
                    case DRDA_TYPDEF_QTDSQLASC:
                        u32_sqlcode1 = ntohl(u32_sqlcode);
                        *p_i_sqlcode = (int)u32_sqlcode1;
                        p_st_sess->i_ser_typdef = DRDA_TYPDEF_QTDSQLX86;
                        break;
                }
            }
        }
        else
        {
            return APM_L7_ANALYZE_FAIL;
        }

        /* 上述修正还不够 */
        if (*p_i_sqlcode < -99999)
        {
            u32_sqlcode1 = *p_i_sqlcode;
            u32_sqlcode2 = ntohl(u32_sqlcode1);
            i_sqlcode = (int)u32_sqlcode2;
            if (i_sqlcode > -99999)
            {
                switch (p_st_sess->i_ser_typdef)
                {
                    /* 小头的转大头 */
                    case DRDA_TYPDEF_QTDSQLX86:
                    case DRDA_TYPDEF_QTDSQLVAX:
                        *p_i_sqlcode = i_sqlcode;
                        p_st_sess->i_ser_typdef = DRDA_TYPDEF_QTDSQLASC;
                        break;

                    /* 大头的转小头 */
                    case DRDA_TYPDEF_QTDSQL370:
                    case DRDA_TYPDEF_QTDSQL400:
                    case DRDA_TYPDEF_QTDSQLASC:
                        *p_i_sqlcode = i_sqlcode;
                        p_st_sess->i_ser_typdef = DRDA_TYPDEF_QTDSQLX86;
                        break;
                }
            }
        }
    }

    /* 跳过SQLERRPROC */
    bytebuff_skip(p_st_data, 8);

    /* 解析SQLCAXGRP */
    i_ret = db2_parse_exter_sqlcaxgrp(p_st_private);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* 解析sqldiaggrp */
    i_ret = db2_parse_exter_sqldiaggrp(p_st_data);
    return i_ret;
}

/*******************************************************************************
*  FUNC     :  跳过指定bytes
*  ARGS     :  p_st_data (bytebuffer数据)
*           :  ui_skip_len(要跳过的数据长度)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int db2_skip_exter_bytes(Frbyte_Packet *p_st_data
                        , unsigned int ui_skip_len)
{
    /* 数据不足 */
    if (ui_skip_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        return APM_L7_ANALYZE_TODO;
    }

    bytebuff_skip(p_st_data, ui_skip_len);
    return APM_L7_ANALYZE_SUCC;
}


/*******************************************************************************
*  FUNC     :  跳过可变bytes
*  ARGS     :  p_st_data (bytebuffer数据)
*           :  i_double_single(双字节flag)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int db2_skip_exter_varbytes(Frbyte_Packet *p_st_data, int i_double_single)
{
    int i_ret = FR_SUCC;
    uint16_t u16_len = 0;
    unsigned int ui_value_len = 0;

    /* 两个bytes位 */
    /* 数据不足 */
    if (bytebuff_remaining(p_st_data) < 2)
    {
        return APM_L7_ANALYZE_TODO;
    }

    /* 取得长度 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    ui_value_len = u16_len * i_double_single;

    /* 数据不足 */
    if (ui_value_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        bytebuff_set_skip(p_st_data, ui_value_len - bytebuff_remaining(p_st_data));
        return APM_L7_ANALYZE_TODO;
    }

    bytebuff_skip(p_st_data, ui_value_len);
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  跳过大数据
*  ARGS     :  p_st_data (bytebuffer数据)
*           :  i_double_single(双字节flag)
*           :  p_ui_exter_data_count(count)
*           :  pp_exter_type(type)
*           :  i_index(index)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_frdata必须不为NULL
*******************************************************************************/
int db2_skip_exter_lob(Frbyte_Packet *p_st_data
                      , int i_double_single
                      , unsigned int *p_ui_exter_data_count
                      , char **pp_exter_type
                      , int i_index)
{
    int i_ret = FR_SUCC;
    uint8_t u8_extern_flg = 0;
    uint64_t u64_len = 0;
    char *p_exter_type = NULL;

    /* 根据数据包得知:大数据开头由1位index位+8位长度 */
    /* 数据不足 */
    if (bytebuff_remaining(p_st_data) < 1 + 8)
    {
        return APM_L7_ANALYZE_TODO;
    }

    /* 取得extern标识 */
    i_ret = bytebuff_get_char(p_st_data, &u8_extern_flg);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得长度位 */
    i_ret = bytebuff_get_long(p_st_data, 8, &u64_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    u64_len *= i_double_single;
    if (i_index == 2)
    {
        u64_len += 2;
    }
    else if (i_index == 4)
    {
        u64_len += 10;
    }

    /* extern标识为2时数据在extern中 */
    if (u8_extern_flg == 1)
    {
        /* 数据不足 */
        if (u64_len > (unsigned int)bytebuff_remaining(p_st_data))
        {
            bytebuff_set_skip(p_st_data, ((unsigned int)u64_len) - bytebuff_remaining(p_st_data));
            return APM_L7_ANALYZE_TODO;
        }

        /* 跳过数据块 */
        bytebuff_skip(p_st_data, (unsigned int)u64_len);
    }
    else if (u8_extern_flg == 2)
    {
        if (*pp_exter_type == NULL)
        {
            p_exter_type = (char *)frmalloc(64);
            if (p_exter_type == NULL)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            memset(p_exter_type, 0x0, 64);
            *p_exter_type = i_double_single;
            *p_ui_exter_data_count = 1;
            *pp_exter_type = p_exter_type;
        }
        else
        {
            /* 需要重新malloc */
            if (strlen(*pp_exter_type) == *p_ui_exter_data_count + 1)
            {
                p_exter_type = (char *)frmalloc((*p_ui_exter_data_count + 1) * 2);
                if (p_exter_type == NULL)
                {
                    return APM_L7_ANALYZE_FAIL;
                }
                memset(p_exter_type, 0x0, (*p_ui_exter_data_count + 1) * 2);
                memcpy(p_exter_type, *pp_exter_type, *p_ui_exter_data_count);
                frfree(*pp_exter_type);
                *pp_exter_type = p_exter_type;
            }
            else
            {
                p_exter_type = *pp_exter_type;
            }
            p_exter_type[*p_ui_exter_data_count] = i_double_single;
            *p_ui_exter_data_count += 1;
        }
    }
    else
    {
        return APM_L7_ANALYZE_FAIL;
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  跳过一列数据
*  ARGS     :  p_st_data (bytebuffer数据)
*           :  p_lst_metadata(DB2 metadata list)
*           :  p_ui_exter_data_count(count)
*           :  pp_exter_type(type)
*           :  p_i_index(index)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_st_data必须不为NULL
*******************************************************************************/
int db2_skip_exter_one_cloum(Frbyte_Packet *p_st_data
                            , Frlist_header *p_lst_metadata
                            , unsigned int *p_ui_exter_data_count
                            , char **pp_exter_type
                            , int *p_i_index)
{
    int i_ret = FR_SUCC;
    uint8_t u8_flg = 0;
    unsigned int ui_len_tmp = 0;
    Frlist_node *p_st_node = NULL;
    Sql_metadata_info *p_st_metadata = NULL;

    p_st_node = FRLIST_FIRST_NODE(p_lst_metadata);
    while (p_st_node)
    {
        p_st_metadata = (Sql_metadata_info *)FRLIST_GET_NODE_DATA(p_st_node);

        /* 数据不足 */
        if (bytebuff_remaining(p_st_data) < 1)
        {
            return APM_L7_ANALYZE_TODO;
        }

        /* 将数据类型与0x01想与判断该类型是否是Nullable */
        if (p_st_metadata->i_data_type & 0x01)
        {
            /* 取得第一个字节由此判断该Nullable字段是否为NULL */
            i_ret = bytebuff_get_char(p_st_data, &u8_flg);
            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
            if (u8_flg == 0xFF)/* NULL节点 */
            {
                /* 取得下一个节点 */
                p_st_node = FRLIST_NEXT_NODE(p_st_node);
                switch (p_st_metadata->i_data_type)
                {
                    case DRDA_TYPE_NOCD:     //Nullable Large Object Character DBCS
                    case DRDA_TYPE_NOB:      //Nullable Large Object Bytes
                    case DRDA_TYPE_NOCS:     //Nullable Large Object Character SBCS
                    case DRDA_TYPE_NOCM:     //Nullable Large Object Character Mixed
                        *p_i_index += 1;
                        break;
                }
                continue;
            }
        }

        switch (p_st_metadata->i_data_type)
        {
            /* 跳过4byte型数据 */
            case DRDA_TYPE_I4:       //4-byte Integer
            case DRDA_TYPE_NI4:      //Nullable 4-byte Integer
            case DRDA_TYPE_BF4:      //4-byte Basic Floating Point
            case DRDA_TYPE_NBF4:     //Nullable 4-byte Basic Floating Point
                i_ret = db2_skip_exter_bytes(p_st_data, 4);
                break;

            /* 跳过short型数据 */
            case DRDA_TYPE_I2:       //2-byte Integer
            case DRDA_TYPE_NI2:      //Nullable 2-byte Integer
                i_ret = db2_skip_exter_bytes(p_st_data, 2);
                break;

            /* 跳过byte型数据 */
            case DRDA_TYPE_I1:       //1-byte Integer
            case DRDA_TYPE_NI1:      //Nullable 1-byte Integer
                i_ret = db2_skip_exter_bytes(p_st_data, 1);
                break;

            /* 跳过16byte型数据 */
            case DRDA_TYPE_BF16:     //16-byte Basic Floating Point
            case DRDA_TYPE_NBF16:    //Nullable 16-byte Basic Floating Point
                i_ret = db2_skip_exter_bytes(p_st_data, 16);
                break;

            /* 跳过8byte型数据 */
            case DRDA_TYPE_I8:       //Eight-byte Integer
            case DRDA_TYPE_NI8:      //Nullable Eight-byte Integer
            case DRDA_TYPE_BF8:      //8-byte Basic Floating Point
            case DRDA_TYPE_NBF8:     //Nullable 8-byte Basic Floating Point
                i_ret = db2_skip_exter_bytes(p_st_data, 8);
                break;

            /* 跳过固定长度数据 */
            case DRDA_TYPE_FD:       //Fixed Decimal
            case DRDA_TYPE_NFD:      //Nullable Fixed Decimal
                ui_len_tmp = (p_st_metadata->ui_scale)/2 + 1;
                i_ret = db2_skip_exter_bytes(p_st_data, ui_len_tmp);
                break;

            /* 跳过固定长度数据 */
            case DRDA_TYPE_ZD:       //Zoned Decimal
            case DRDA_TYPE_NZD:      //Nullable Zoned Decimal
                i_ret = db2_skip_exter_bytes(p_st_data, p_st_metadata->ui_scale);
                break;

            /* 跳过固定长度数据 */
            case DRDA_TYPE_D:        //Date
            case DRDA_TYPE_ND:       //Nullable Date
            case DRDA_TYPE_T:        //Time
            case DRDA_TYPE_NT:       //Nullable Time
            case DRDA_TYPE_TS:       //Timestamp
            case DRDA_TYPE_NTS:      //Nullable Timestamp
            case DRDA_TYPE_FB:       //Fixed Bytes
            case DRDA_TYPE_NFB:      //Nullable Fixed Bytes
            case DRDA_TYPE_FBIN:     //Fixed Binary
            case DRDA_TYPE_NFBIN:    //Nullable Fixed Binary
            case DRDA_TYPE_FCM:      //Fixed Character Mixed
            case DRDA_TYPE_NFCM:     //Nullable Fixed Character Mixed
            case DRDA_TYPE_FCS:      //Fixed Character SBCS
            case DRDA_TYPE_NFCS:     //Nullable Fixed Character SBCS
                i_ret = db2_skip_exter_bytes(p_st_data, p_st_metadata->ui_len);
                break;

            /* ���̶�������� */
            case DRDA_TYPE_LVCS:     //Long Variable Character SBCS
            case DRDA_TYPE_NLVCS:    //Nullable Long Variable Character SBCS
            case DRDA_TYPE_LVB:      //Long Variable Bytes
            case DRDA_TYPE_NLVB:     //Nullable Long Variable Bytes
            case DRDA_TYPE_LVCM:     //Long Variable Character Mixed
            case DRDA_TYPE_NLVCM:    //Nullable Long Variable Character Mixed
                *p_i_index += 1;

            case DRDA_TYPE_VB:       //Variable Bytes
            case DRDA_TYPE_NVB:      //Nullable Variable Bytes
            case DRDA_TYPE_VCM:      //Variable Character Mixed
            case DRDA_TYPE_NVCM:     //Nullable Variable Character Mixed
            case DRDA_TYPE_VCS:      //Variable Character SBCS
            case DRDA_TYPE_NVCS:     //Nullable Variable Character SBCS
            case DRDA_TYPE_VBIN:     //Variable Binary
            case DRDA_TYPE_NVBIN:    //Nullable Variable Binary
                i_ret = db2_skip_exter_varbytes(p_st_data, DB2_SINGLE);
                break;

            /* 跳过不固定长度数据 */
            case DRDA_TYPE_FCD:      //Fixed Character DBCS
            case DRDA_TYPE_NFCD:     //Nullable Fixed Character DBCS
                i_ret = db2_skip_exter_bytes(p_st_data, (p_st_metadata->ui_len) * 2);
                break;

            /* 跳过固定长度双字节数据 */
            case DRDA_TYPE_LVCD:     //Long Variable Character DBCS
            case DRDA_TYPE_NLVCD:    //Nullable Long Variable Character DBCS
                *p_i_index += 1;

            case DRDA_TYPE_VCD:      //Variable Character DBCS
            case DRDA_TYPE_NVCD:     //Nullable Variable Character DBCS
                i_ret = db2_skip_exter_varbytes(p_st_data, DB2_DOUBLE);
                break;

            case DRDA_TYPE_OCD:      //Large Object Character DBCS
            case DRDA_TYPE_NOCD:     //Nullable Large Object Character DBCS
                *p_i_index += 1;
                i_ret = db2_skip_exter_lob(p_st_data, DB2_DOUBLE
                                          , p_ui_exter_data_count
                                          , pp_exter_type
                                          , *p_i_index);
                break;

            case DRDA_TYPE_XMLSIE:   //XML String Internal Encoding
            case DRDA_TYPE_NXMLSIE:  //Nullable XML String Internal Encoding
            case DRDA_TYPE_XMLSEE:   //XML String External Encoding
            case DRDA_TYPE_NXMLSEE:  //Nullable XML String External Encoding
            case DRDA_TYPE_OB:       //Large Object Bytes
            case DRDA_TYPE_NOB:      //Nullable Large Object Bytes
            case DRDA_TYPE_OCS:      //Large Object Character SBCS
            case DRDA_TYPE_NOCS:     //Nullable Large Object Character SBCS
            case DRDA_TYPE_OCM:      //Large Object Character Mixed
            case DRDA_TYPE_NOCM:     //Nullable Large Object Character Mixed
                *p_i_index += 1;
                i_ret = db2_skip_exter_lob(p_st_data, DB2_SINGLE
                                          , p_ui_exter_data_count
                                          , pp_exter_type
                                          , *p_i_index);
                break;

            /* 未解析到的数据类型 */
            case DRDA_TYPE_N:        //Numeric Character
            case DRDA_TYPE_NN:       //Nullable Numeric Character
            case DRDA_TYPE_RI:       //Row Identifier
            case DRDA_TYPE_NRI:      //Nullable Row Identifier
            case DRDA_TYPE_RSL:      //Result Set Locator
            case DRDA_TYPE_NRSL:     //Nullable Result Set Locator
            case DRDA_TYPE_OBL:      //Large Object Bytes Locator
            case DRDA_TYPE_NOBL:     //Nullable Large Object Bytes Locator
            case DRDA_TYPE_OCL:      //Large Object Character Locator
            case DRDA_TYPE_NOCL:     //Nullable Large Object Character Locator
            case DRDA_TYPE_OCDL:     //Large Object Character DBCS Locator
            case DRDA_TYPE_NOCDL:    //Nullable Large Obj. Char. DBCS Locator
            case DRDA_TYPE_NTM:      //Null-Terminated Mixed
            case DRDA_TYPE_NNTM:     //Nullable Null-Terminated Mixed
            case DRDA_TYPE_PLB:      //Pascal L String Bytes
            case DRDA_TYPE_NPLB:     //Nullable Pascal L String Bytes
            case DRDA_TYPE_PLS:      //Pascal L String SBCS
            case DRDA_TYPE_NPLS:     //Nullable Pascal L String SBCS
            case DRDA_TYPE_PLM:      //Pascal L String Mixed
            case DRDA_TYPE_NPLM:     //Nullable Pascal L String Mixed
            case DRDA_TYPE_DLS:      //SBCS Datalink
            case DRDA_TYPE_NDLS:     //Nullable SBCS Datalink
            case DRDA_TYPE_DLM:      //Mixed-byte Datalink
            case DRDA_TYPE_NDLM:     //Nullable Mixed-byte Datalink
            case DRDA_TYPE_TSTZ:     //Timestamp with Time Zone
            case DRDA_TYPE_NTSTZ:    //Nullable Timestamp with Time Zone
            case DRDA_TYPE_CUR:      //Cursor Type
            case DRDA_TYPE_NCUR:     //Nullable Cursor Type
            case DRDA_TYPE_DFP:      //Decimal Floating Point
            case DRDA_TYPE_NDFP:     //Nullable Decimal Floating Point
            case DRDA_TYPE_XMLBIN:   //XML Binary
            case DRDA_TYPE_NXMLBIN:  //Nullable XML Binary
            case DRDA_TYPE_BL:       //Boolean
            case DRDA_TYPE_NBL:      //Nullable Boolean
            case DRDA_TYPE_NTB:      //Null-Terminated Bytes
            case DRDA_TYPE_NNTB:     //Nullable Null-Terminated Bytes
            case DRDA_TYPE_NTCS:     //Null-Terminated SBCS
            case DRDA_TYPE_NNTCS:    //Nullable Null-Terminated SBCS
                frdbg("TODO, [%02X]need to parse!\n", p_st_metadata->i_data_type);
                return APM_L7_ANALYZE_FAIL;

            default:
                frdbg("Unknow data type!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            return i_ret;
        }
        /* 取得下一个节点 */
        p_st_node = FRLIST_NEXT_NODE(p_st_node);
    }

    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析数据
*  ARGS     :  p_st_data (bytebuffer数据)
*           :  i_exter_data_count(count)
*           :  p_exter_type(type)
*           :  p_i_whole_flg(index)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_skip_exter_data(Frbyte_Packet *p_st_data
                       , int i_exter_data_count
                       , char *p_exter_type
                       , int *p_i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    uint8_t u8_ddm_id = 0;
    uint16_t u16_cp = 0;
    uint16_t u16_len = 0;
    int i_extended_num = 0;
    uint16_t u16_ddm_len = 0;
    uint32_t u32_extended_len = 0;
    uint64_t u64_extended_len = 0;
    unsigned int ui_extended_len = 0;
    int i_last_flg = DB2_FALSE;
    int i_loop = 0;

    while (i_loop < i_exter_data_count)
    {
        /* 判断遗留长度是否足够存下一个完整的DDM header */
        if (bytebuff_remaining(p_st_data) < DRDA_DDM_HD_LEN)
        {
            return APM_L7_ANALYZE_TODO;
        }
        /* 取得整个DDM长度(2) */
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
        /* DDM长度必须大于等于10(DDM header的长度是10) */
        if (i_ret != FR_SUCC || u16_len < DRDA_DDM_HD_LEN)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        /* 跳过DDMID(1) */
        bytebuff_skip(p_st_data, 1);
        /* 取得FORMATID */
        i_ret = bytebuff_get_char(p_st_data, &u8_ddm_id);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
        /* 最后标示 */
        if ((u8_ddm_id & 0x40) == 0)
        {
            i_last_flg = DB2_TRUE;
        }

        /* 跳过RQSDRR(2) */
        bytebuff_skip(p_st_data, 2);
        /* 取得长度位 */
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_ddm_len, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        /* 取得DDM CODE POINT */
        i_ret = bytebuff_get_short(p_st_data, 2, &u16_cp, BYTE_BIG_ENDIAN);
        if (i_ret != FR_SUCC || u16_cp != DRDA_CP_EXTDTA)
        {
            return APM_L7_ANALYZE_FAIL;
        }

        /* Check if this DDM has extended length field */
        if (u16_ddm_len & DB2_CONTINUATION_BIT)
        {
            i_extended_num = u16_ddm_len - DB2_CONTINUATION_BIT - 4;
            if (i_extended_num > bytebuff_remaining(p_st_data))
            {
                return APM_L7_ANALYZE_TODO;
            }

            switch (i_extended_num)
            {
                case 8:
                case 6:
                    i_ret = bytebuff_get_long(p_st_data, i_extended_num
                                             , &u64_extended_len
                                             , BYTE_BIG_ENDIAN);
                    ui_extended_len = (unsigned int)u64_extended_len;
                    ui_extended_len += 2;
                    break;

                case 4:
                    i_ret = bytebuff_get_int(p_st_data, i_extended_num
                                            , &u32_extended_len
                                            , BYTE_BIG_ENDIAN);
                    ui_extended_len = (unsigned int)u32_extended_len;
                    ui_extended_len += 2;
                    break;

                case 0:
                    ui_extended_len = u16_len - DRDA_DDM_HD_LEN;
                    break;

                default:
                    return APM_L7_ANALYZE_FAIL;

            }

            if (i_ret != FR_SUCC)
            {
                return APM_L7_ANALYZE_FAIL;
            }
        }
        else if (u16_ddm_len != u16_len - 6)/* 长度判断 */
        {
            return APM_L7_ANALYZE_FAIL;
        }
        else
        {
            ui_extended_len = u16_ddm_len - 4;
        }

        if (p_exter_type[i_loop] == DB2_DOUBLE)
        {
            /* 数据不足 */
            if (ui_extended_len > (unsigned int)bytebuff_remaining(p_st_data))
            {
                bytebuff_set_skip(p_st_data, ui_extended_len - bytebuff_remaining(p_st_data));
                return APM_L7_ANALYZE_TODO;
            }
            bytebuff_skip(p_st_data, ui_extended_len);
        }

        /* 数据不足 */
        if (ui_extended_len > (unsigned int)bytebuff_remaining(p_st_data))
        {
            bytebuff_set_skip(p_st_data, ui_extended_len - bytebuff_remaining(p_st_data));
            return APM_L7_ANALYZE_TODO;
        }
        bytebuff_skip(p_st_data, ui_extended_len);
        i_loop++;
    }

    if (i_last_flg == DB2_TRUE)
    {
        *p_i_whole_flg = DB2_TRUE;
        return APM_L7_ANALYZE_SUCC;
    }

    /* 判断遗留长度是否足够存下一个完整的DDM header */
    if (bytebuff_remaining(p_st_data) < DRDA_DDM_HD_LEN)
    {
        return APM_L7_ANALYZE_TODO;
    }
    /* 取得整个DDM长度(2) */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_len, BYTE_BIG_ENDIAN);
    /* DDM长度必须大于等于10(DDM header的长度是10) */
    if (i_ret != FR_SUCC || u16_len < DRDA_DDM_HD_LEN)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 跳过DDMID(1) */
    bytebuff_skip(p_st_data, 1);
    /* 取得FORMATID */
    i_ret = bytebuff_get_char(p_st_data, &u8_ddm_id);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }
    /* 最后标示 */
    if ((u8_ddm_id & 0x40) == 0)
    {
        i_last_flg = DB2_TRUE;
    }

    /* 跳过RQSDRR(2) */
    bytebuff_skip(p_st_data, 2);
    /* 取得长度位 */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_ddm_len, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* 取得DDM CODE POINT */
    i_ret = bytebuff_get_short(p_st_data, 2, &u16_cp, BYTE_BIG_ENDIAN);
    if (i_ret != FR_SUCC || u16_cp != DRDA_CP_SQLCARD)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    /* Check if this DDM has extended length field */
    if (u16_ddm_len & DB2_CONTINUATION_BIT)
    {
        i_extended_num = u16_ddm_len - DB2_CONTINUATION_BIT - 4;
        if (i_extended_num > bytebuff_remaining(p_st_data))
        {
            return APM_L7_ANALYZE_TODO;
        }

        switch (i_extended_num)
        {
            case 8:
            case 6:
                i_ret = bytebuff_get_long(p_st_data, i_extended_num
                                         , &u64_extended_len
                                         , BYTE_BIG_ENDIAN);
                ui_extended_len = (unsigned int)u64_extended_len;
                ui_extended_len += 2;
                break;

            case 4:
                i_ret = bytebuff_get_int(p_st_data, i_extended_num
                                        , &u32_extended_len
                                        , BYTE_BIG_ENDIAN);
                ui_extended_len = (unsigned int)u32_extended_len;
                ui_extended_len += 2;
                break;

            case 0:
                ui_extended_len = u16_len - DRDA_DDM_HD_LEN;
                break;

            default:
                return APM_L7_ANALYZE_FAIL;

        }

        if (i_ret != FR_SUCC)
        {
            return APM_L7_ANALYZE_FAIL;
        }
    }
    else if (u16_ddm_len != u16_len - 6)/* 长度判断 */
    {
        return APM_L7_ANALYZE_FAIL;
    }
    else
    {
        ui_extended_len = u16_ddm_len - 4;
    }

    /* 数据不足 */
    if (ui_extended_len > (unsigned int)bytebuff_remaining(p_st_data))
    {
        bytebuff_set_skip(p_st_data, ui_extended_len - bytebuff_remaining(p_st_data));
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_skip(p_st_data, ui_extended_len);

    *p_i_whole_flg = i_last_flg;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析数据
*  ARGS     :  p_st_data (bytebuffer数据)
*           :  p_lst_metadata(DB2 metadata list)
*           :  p_ll_rows(fetch行数)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_get_exter_fetch_rows(L7session_db2_private *p_st_private
                            , Frlist_header *p_lst_metadata
                            , unsigned long *p_ul_rows)
{
    uint8_t u8_flg = 0;
    uint8_t u8_end = 0;
    int i_ret = FR_SUCC;
    int i_whole_flg = DB2_FALSE;
    int i_sqlcode = 0;
    unsigned long ul_rows = 0;
    unsigned int ui_exter_data_count = 0;
    char *p_exter_type = NULL;
    char arr_sqlstate[6] = {0};
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;
    int i_loop = 0;

    while (bytebuff_remaining(p_st_data) > 0)
    {
        /* 跳过sqlcagrp */
        i_ret = db2_parse_exter_sqlcagrp(p_st_private, &i_sqlcode, arr_sqlstate);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            db2_free((void **)&p_exter_type);
            return i_ret;
        }

        /* fetch的最后一行 */
        if (i_sqlcode == 100 || memcmp(arr_sqlstate, "02000", 5) == 0)
        {
            if (bytebuff_remaining(p_st_data))
            {
                i_ret = bytebuff_peek_char(p_st_data, &u8_end);
                if (i_ret == FR_SUCC && u8_end == 0xFF)
                {
                    bytebuff_skip(p_st_data, 1);
                }
            }
            p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
            p_st_fragment->i_exter_whole_flg = DB2_TRUE;
            *p_ul_rows = ul_rows;
            db2_free((void **)&p_exter_type);
            return APM_L7_ANALYZE_SUCC;
        }

        /* 数据不足 */
        if (bytebuff_remaining(p_st_data) < 1)
        {
            db2_free((void **)&p_exter_type);
            return APM_L7_ANALYZE_TODO;
        }
        /* 取得第一个字节由此判断该行是否为NULL */
        i_ret = bytebuff_get_char(p_st_data, &u8_flg);
        if (i_ret != FR_SUCC)
        {
            db2_free((void **)&p_exter_type);
            return APM_L7_ANALYZE_FAIL;
        }

        /* 当前列数据为NULL */
        if (u8_flg == 0xFF)
        {
            continue;
        }
        /* 解析当前列 */
        else if (u8_flg == 0x00)
        {
            i_ret = db2_skip_exter_one_cloum(p_st_data, p_lst_metadata
                                            , &ui_exter_data_count
                                            , &p_exter_type
                                            , &i_loop);
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                db2_free((void **)&p_exter_type);
                return i_ret;
            }
        }
        else
        {
            db2_free((void **)&p_exter_type);
            return APM_L7_ANALYZE_FAIL;
        }
        ul_rows++;

        /* 有要解析的exter数据 */
        if (ui_exter_data_count)
        {
            i_ret = db2_skip_exter_data(p_st_data, ui_exter_data_count
                                       , p_exter_type, &i_whole_flg);
            db2_free((void **)&p_exter_type);
            ui_exter_data_count = 0;
            if (i_ret != APM_L7_ANALYZE_SUCC)
            {
                db2_free((void **)&p_exter_type);
                return i_ret;
            }
            if (i_whole_flg == DB2_TRUE)
            {
                p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
                p_st_fragment->i_exter_whole_flg = DB2_TRUE;
                *p_ul_rows = ul_rows;
                return APM_L7_ANALYZE_SUCC;
            }
        }
    }

    db2_free((void **)&p_exter_type);
    return APM_L7_ANALYZE_TODO;
}
